import math

import numpy as np
import scipy.constants
from scipy.special import j0
from scipy.integrate import quad
from typing import List

"""
1. [X] Path Loss
2. [ ] Shadowing
3. [ ] small-scale fading
"""


def transmission_rate(node_1, node_2, beta_0, alpha, g, SIGMA_2):  # node_1为发送端
    distance = np.linalg.norm(node_1.location - node_2.location)
    beta = beta_0 / np.power(distance ** 2, alpha / 2)
    h_2 = beta * g
    rate = node_1.bandwidth * np.log2(1 + node_1.t_power * h_2 / SIGMA_2)
    return rate


def calculate_channel_gain(node_1, node_2, a, b, mu_LOS, mu_NLoS):
    """
    参数：
    SN_node：信号节点对象
    other_node：另一信号节点对象（UAV 或 Train）
    fc：float，上行链路信道频率（Hz）
    mu_LOS：float，LoS信道的额外衰减因子
    mu_NLoS：float，NLoS信道的额外衰减因子
    """
    H = 50
    # 计算节点间的三维距离
    d_km = np.linalg.norm(node_1.location - node_2.location)
    d_2d = math.sqrt(d_km ** 2 + H ** 2)  # 加上垂直高度
    # 计算仰角 θ_km
    theta_km = (180 / math.pi) * math.asin(H / d_2d)
    # 计算 LoS 概率 p_LOS_km 和 NLoS 概率 p_NLoS_km
    p_LOS_km = 1 / (1 + a * math.exp(-b * (theta_km - a)))
    p_NLoS_km = 1 - p_LOS_km
    # 计算信道损耗 PL_LOS_km 和 PL_NLoS_km
    c = 3e8  # 光速 (m/s)
    PL_LOS_km = 20 * math.log10((4 * math.pi * node_1.f * d_km) / c) + mu_LOS
    PL_NLoS_km = 20 * math.log10((4 * math.pi * node_1.f * d_km) / c) + mu_NLoS
    # 计算信道增益 g_km
    g_km = (p_LOS_km * 10 ** (-PL_LOS_km / 10)) + (p_NLoS_km * 10 ** (-PL_NLoS_km / 10))
    return g_km


def data_rate(node_1, node_2, a, b, mu_LOS, mu_NLoS, SIGMA_2):
    g_km = calculate_channel_gain(node_1, node_2, a, b, mu_LOS, mu_NLoS)
    # 计算信干噪比 γ_km
    gamma_km = (node_1.t_power * g_km) / SIGMA_2
    # 计算数据传输速率 R_km
    R_km = node_1.bandwidth * math.log2(1 + gamma_km)
    return R_km


def UtoT_data_rate(node_1, Train_node, a, b, mu_LOS, mu_NLoS, SIGMA_2, I_ici):
    g_km = calculate_channel_gain(node_1, Train_node, a, b, mu_LOS, mu_NLoS)
    # 计算信干噪比 γ_km
    gamma_km = (node_1.t_power * g_km) / SIGMA_2 + g_km * I_ici
    # 计算数据传输速率 R_km
    R_km = node_1.bandwidth * math.log2(1 + gamma_km)
    return R_km


def doppler_interference_factor(fm_T, vT, c, Ts):
    # 被积函数定义
    def integrand(tau):
        term = 2 * np.pi * fm_T * (-vT / c) * Ts  # 参数计算
        return 1 - abs(tau) * j0(term)  # 被积函数 1 - |τ| * J_0(...)
    # 执行积分，积分范围为 [-1, 1]
    integral_result = quad(integrand, -1, 1)[0]
    # 计算多普勒干扰因子
    I_ICI = 1 - integral_result
    return I_ICI
